package com.ruoyi.web.controller.textbook;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.vo.PageResult;
import com.ruoyi.exam.domain.Category;
import com.ruoyi.exam.domain.Subject;
import com.ruoyi.subject.SubjectService;
import com.ruoyi.textbook.domain.Textbook;
import com.ruoyi.textbook.service.ITextbookService;
import com.ruoyi.textbook.vo.TextbookListVO;
import com.ruoyi.web.controller.textbook.vo.TextbookData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/textbook")
public class TextbookController extends BaseController {
    @Autowired
    private ITextbookService textbookService;
    @Autowired
    private SubjectService subjectService;

    @Value("${ruoyi.exam.frontAddress}")
    private String frontAddress;

    @PreAuthorize("@ss.hasPermi('textbook:list')")
    @RequestMapping("/list")
    public TableDataInfo list(TextbookListVO listVO) {
        PageResult<Textbook> result = textbookService.page(listVO);
        List<Category> categories = subjectService.getSubjectCategory();
        Map<Integer, Map<String, Object>> map = categories.stream()
                .collect(Collectors.toMap(Category::getCategory, category -> category.toMap()));
        if (result.getData() != null) {
           List<TextbookData> list = result.getData().stream().map(textbook -> {
                TextbookData data = new TextbookData(textbook, buildReadUrl(textbook.getId()));
                setTextbookSubjectData(map, data);
                return data;
            }).collect(Collectors.toList());
            PageResult<TextbookData> tmp = new PageResult<>(result.getPage() ,result.getPageSize() ,result.getTotal());
            tmp.addAll(list);
            return getDataTable(tmp.convertToPage());
        }
        return getDataTable(result.convertToPage());
    }

    @PreAuthorize("@ss.hasPermi('textbook:upload')")
    @RequestMapping("/upload")
    public AjaxResult uploadTextbook(MultipartFile file) throws Exception {
        Textbook textbook = textbookService.upload(file.getInputStream(), file.getOriginalFilename());
        return AjaxResult.success(textbook);
    }

    @RequestMapping("/info")
    public AjaxResult info(int id){
        Textbook textbook = textbookService.get(id);
        return AjaxResult.success(textbook);
    }

    @RequestMapping("/read")
    public void read(int id ,HttpServletRequest req , HttpServletResponse response) throws Exception{
        Textbook textbook = textbookService.get(id);
        File file = ResourceUtils.getFile(textbook.getUri());
        if(textbook.getType() == 0) {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;fileName=" + textbook.getName());

            response.getOutputStream().write(FileUtil.readBytes(file));
        }else if(textbook.getType() == 1){
            readVideo(file ,req ,response);
        }
    }

    private void readVideo(File file ,HttpServletRequest req ,HttpServletResponse response) throws Exception{
        long fl = file.length();

        String rangeStr = req.getHeader("Range");
        long range = 0L;
        if(StrUtil.isNotBlank(rangeStr)){
            range = Long.parseLong(rangeStr.substring(rangeStr.indexOf("=") + 1 ,rangeStr.indexOf("-")));
        }
        response.setHeader("Content-type", "video/mp4");
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

        RandomAccessFile randomAccessFile = new RandomAccessFile(file ,"r");
        randomAccessFile.seek(range);
        byte[] bytes = new byte[1024 * 1024];
        int len = randomAccessFile.read(bytes);
        response.setContentLength(len);
        response.setHeader("Content-Range", "bytes " + range + "-" + (fl - 1) + "/" + fl);

        OutputStream os = response.getOutputStream();
        os.write(bytes, 0 ,len);
        os.close();
        randomAccessFile.close();
    }

    /**
     * 构建教材阅读地址
     *
     * @param textbookId
     * @return
     */
    private String buildReadUrl(int textbookId) {
        return frontAddress + "/evaluate/textbook/read?id=" + textbookId;
    }

    /**
     * 设置教材科目类别
     *
     * @param map  类别map
     * @param data 教材
     */
    private void setTextbookSubjectData(Map<Integer, Map<String, Object>> map, TextbookData data) {
        Map<String, Object> cm = map.get(data.getCategoryId());
        if (cm != null) {
            if (data.getCategoryId() != null) {
                data.setCategory((String) cm.get("name"));
            }
            if (data.getSubjectId() != null) {
                Map<Integer, Subject> subMap = (Map<Integer, Subject>) cm.get("subjects");
                if (subMap != null) {
                    Subject subject = subMap.get(data.getSubjectId());
                    if (subject != null) {
                        data.setSubject(subject.getName());
                    }
                }
            }
        }
    }

    @PreAuthorize("@ss.hasPermi('textbook:update')")
    @PostMapping("/update")
    public AjaxResult update(@RequestBody Textbook textbook){
        textbookService.update(textbook);
        return AjaxResult.success();
    }

    @PreAuthorize("@ss.hasPermi('textbook:del')")
    @PostMapping("/del")
    public AjaxResult del(int id){
        textbookService.del(id);
        return AjaxResult.success();
    }
}
